from .relation import Connected
from .yinyang import YinYang
from .wuxing import WuXing
from .zp_utils import combine


class Gan:
    """
    天干：只使用get_item返回指定的对象
    """
    _cache = {}
    _inited = False

    def __new__(cls, name, no, yinyang, wuxing):
        if cls._inited:
            raise RuntimeError(f'{cls.__name__} 已经加载，不能直接实例化，请使用 {cls.__name__}.get_item')
        if name in cls._cache:
            return cls._cache[name]
        else:
            self = super().__new__(cls)
            cls._cache[name] = self
            return self

    def __init__(self, name, no, yinyang, wuxing):
        self.name = name
        self.no = no  # 编号
        self.yinyang = YinYang.get_item(yinyang)
        self.wuxing = WuXing.get_item(wuxing)

    @classmethod
    def init_gans(cls, items):
        """
        初始化的时候调用一次
        """
        for name, yinyang, wuxing, no in items:
            cls(name, no, yinyang, wuxing)
        cls._inited = True

    @classmethod
    def get_item(cls, name):
        """
        返回指定的对象
        """
        return cls._cache[name]

    def __str__(self):
        return f'{self.name}{self.yinyang.name}{self.wuxing.name}'


class GanChong:
    """
    天干相冲
    """
    _cache = {}
    _inited = False

    def __new__(cls, gan1, gan2):
        if cls._inited:
            raise RuntimeError(f'{cls.__name__} 已经加载，不能直接实例化，请使用 {cls.__name__}.get_item')
        if gan1 > gan2:
            gan1, gan2 = gan2, gan1
        key = (gan1, gan2)
        if key in cls._cache:
            return cls._cache[key]
        else:
            self = super().__new__(cls)
            cls._cache[key] = self
            return self

    def __init__(self, gan1, gan2):
        self.gan1 = Gan.get_item(gan1)
        self.gan2 = Gan.get_item(gan2)

    @classmethod
    def init_gans_chong(cls, items):
        """
        初始化的时候调用一次
        """
        for gan1, gan2 in items:
            cls(gan1, gan2)
        cls._inited = True

    @classmethod
    def get_item(cls, gan1, gan2):
        """
        返回指定的对象
        """
        if gan1 > gan2:
            gan1, gan2 = gan2, gan1
        key = (gan1, gan2)
        return cls._cache.get(key)  # 不相冲就返回None

    @classmethod
    def calc_gan_chong(cls, mingpan):
        ans = []
        for tg_cell1, tg_cell2 in combine([zhu[0] for zhu in mingpan.sizhu], 2):
            match = cls.get_item(tg_cell1.gan.name, tg_cell2.gan.name)
            if match:
                ans.append(Connected(match, mingpan, [tg_cell1, tg_cell2]))
        return ans

    def __str__(self):
        return f'{self.gan1.name}{self.gan2.name}相冲'


class GanHe:
    """
    天干相合
    """
    _cache = {}
    _inited = False

    def __new__(cls, gan1, gan2, wuxing, m_dz, name):
        if cls._inited:
            raise RuntimeError(f'{cls.__name__} 已经加载，不能直接实例化，请使用 {cls.__name__}.get_item')
        if gan1 > gan2:
            gan1, gan2 = gan2, gan1
        key = (gan1, gan2)
        if key in cls._cache:
            return cls._cache[key]
        else:
            self = super().__new__(cls)
            cls._cache[key] = self
            return self

    def __init__(self, gan1, gan2, wuxing, m_dz, name):
        self.gan1 = Gan.get_item(gan1)
        self.gan2 = Gan.get_item(gan2)
        self.wuxing = WuXing.get_item(wuxing)
        self.m_dz = m_dz  # 只有在这几个月才能合化成功
        self.name = name

    @classmethod
    def init_gans_he(cls, items):
        """
        初始化的时候调用一次
        """
        for gan1, gan2, wuxing, m_dz, name in items:
            cls(gan1, gan2, wuxing, m_dz, name)
        cls._inited = True

    @classmethod
    def get_item(cls, gan1, gan2):
        """
        返回指定的对象
        """
        if gan1 > gan2:
            gan1, gan2 = gan2, gan1
        key = (gan1, gan2)
        return cls._cache.get(key)  # 不相合就返回None

    @classmethod
    def calc_gan_he(cls, mingpan):
        sizhu = mingpan.sizhu
        gans = [zhu[0] for zhu in sizhu]
        # gans_wx = [tg_cell.gan.wuxing.name for tg_cell in gans]
        # m_dz = mingpan.yueling.zhi.name
        ans = []
        for tg_cell1, tg_cell2 in combine(gans, 2):
            match = cls.get_item(tg_cell1.gan.name, tg_cell2.gan.name)
            if match:  # and m_dz in match.m_dz and match.wuxing.name in gans_wx:
                # 1.有相合 2.月令好 3.五行透出
                ans.append(Connected(match, mingpan, [tg_cell1, tg_cell2]))
        return ans

    def __str__(self):
        return f'{self.gan1.name}{self.gan2.name}合{self.wuxing.name}'
